package top.xiaoazi.futureletterserver.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import top.xiaoazi.futureletterserver.common.AppVariable;
import top.xiaoazi.futureletterserver.module.user.entity.User;
import top.xiaoazi.futureletterserver.module.user.service.UserService;
import top.xiaoazi.futureletterserver.module.user.vo.UserRedisVO;
import top.xiaoazi.futureletterserver.utils.JwtUtils;
import top.xiaoazi.futureletterserver.common.R;
import top.xiaoazi.futureletterserver.utils.RedisUtils;
import top.xiaoazi.futureletterserver.utils.RequestUtils;


/**
 * 登录拦截器
 */
@Slf4j
@Configuration
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private RequestUtils requestUtils;

    @Autowired
    private UserService userService;

    /**
     * true -> 用户已登录
     * false -> 用户未登录
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 解决跨域问题(前后端不在同一个端口上)，由于跨域会先发一个诱导请求，这里没有携带任何请求头，所以发现是诱导请求直接放行即可
        if("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            return true;
        }
        String token = request.getHeader(AppVariable.HEADER_TOKEN);
        R r = new R();
        r.setCode(requestUtils.NOT_LOGIN_STATE);
        r.setMsg(requestUtils.NOT_LOGIN_MESSAGE);
        // 判断 redis 是否存在 token
        // redis 里存在 token 不存在返回 false
        if (token == null || !redisUtils.hasKey(token)) {
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            // 将R对象转换成JSON字符串并写入响应体
            objectMapper.writeValue(response.getWriter(), r);
            return false;
        }

        // 走到这表示存在 token 的 key，判断该 token 是否过期
        if (!jwtUtils.validateToken(token)) {
            // 过期删除
            redisUtils.delete(token);
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            // 将R对象转换成JSON字符串并写入响应体
            objectMapper.writeValue(response.getWriter(), r);
            return false;
        }

        // 判断该用户是否修改密码，也就是 redis 缓存中的 密码是否相同
        UserRedisVO userRedisVO = (UserRedisVO) redisUtils.get(token);  // 通过 token 作为 key 获取对于的 user 对象
        User user = userService.getByUserId(userRedisVO.getUserId());
        if (!user.getPassword().equals(userRedisVO.getPassword())) {
            // 修改密码了，这个 token 无效了
            redisUtils.delete(token);
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            // 将R对象转换成JSON字符串并写入响应体
            objectMapper.writeValue(response.getWriter(), r);
            return false;
        }
        return true;
    }
}
